import { arriveTo, goTo } from '@/modules/move'
import { getCreepWorking } from '@/utils/common'

export const crossBuilderFn = (creep: Creep) => {
    if (creep.memory.boost && !creep.memory.boost.done) {
        return
    }

    // 准备，去 storage 或者 terminal 中拿能量
    if (!creep.memory.ready && creep.store.getFreeCapacity('energy') <= 0) {
        creep.memory.ready = true
    }

    if (!creep.memory.ready) {
        const target = creep.room.storage || creep.room.terminal
        if (!target) return
        if (target.store['energy'] < 10000) return
        if (creep.pos.isNearTo(target)) {
            creep.withdraw(target, 'energy')
        } else {
            goTo(creep, target.pos)
        }
        return
    }
    if (creep.hits < creep.hitsMax && creep.getActiveBodyparts(HEAL) > 0) {
        creep.heal(creep)
    }
    // 去目标房间
    const { targetRoom, targetShard } = creep.memory.data as {
        targetRoom: string
        targetShard: string
        sign: string
    }
    if (!targetRoom || !targetShard) return
    if (creep.room.name !== targetRoom || Game.shard.name !== targetShard) {
        arriveTo(creep, new RoomPosition(25, 25, targetRoom), targetShard, 10)
        return
    }

    if (creep.store.getUsedCapacity() === 0 && creep.ticksToLive! < 30) {
        creep.suicide()
        return
    }

    getCreepWorking(creep, creep.store.getCapacity() > 400 ? 0.15 : 1)

    const room = creep.room
    if (!creep.memory.working) {
        if (Game.flags[`${room.name}/helpBuilder/suicide`]) {
            creep.suicide()
            return
        }
        if (!creep.memory.sourceId) {
            if (creep.memory.targetId) delete creep.memory.targetId
            let flag: Flag
            // 如果有 storage 或者 terminal
            if (room.terminal && room.terminal.store['energy'] > 20000) {
                creep.memory.sourceId = room.terminal.id
            } else if (room.storage && room.storage.store['energy'] > 20000) {
                creep.memory.sourceId = room.storage.id
            } else if ((flag = Game.flags[`${room.name}/ruin/energy`])) {
                const ruins = room.find(FIND_RUINS, { filter: (s) => s.store['energy'] > 1000 })
                if (ruins.length) {
                    creep.memory.sourceId = ruins[0].id
                } else {
                    // 移除旗帜，避免之后重复搜索
                    flag.remove()
                }
            } else if ((flag = Game.flags[`${room.name}/drop/energy`])) {
                const dropEnergy = room.find(FIND_DROPPED_RESOURCES, {
                    filter: (s) => s.resourceType === 'energy' && s.amount > 400,
                })
                if (dropEnergy.length) {
                    creep.memory.sourceId = dropEnergy[0].id
                } else {
                    // 移除旗帜，避免之后重复搜索
                    flag.remove()
                }
            } else {
                const sources = room.find(FIND_SOURCES).filter((s) => s.energy > 0)
                if (sources.length > 0) {
                    const closestSource = creep.pos.findClosestByPath(sources)
                    if (closestSource) {
                        creep.memory.sourceId = closestSource.id
                    }
                }
            }
        }
        if (!creep.memory.sourceId) return
        const source = Game.getObjectById(creep.memory.sourceId) as Source | StructureStorage | StructureTerminal
        if (!source) {
            delete creep.memory.sourceId
            return
        }
        if (source instanceof Source) {
            if (source.energy <= 0) {
                delete creep.memory.sourceId
                return
            }
            if (creep.pos.isNearTo(source)) {
                creep.harvest(source)
            } else {
                goTo(creep, source.pos)
            }
        } else if (source instanceof Resource) {
            if (source.amount <= 0) {
                delete creep.memory.sourceId
                return
            }
            if (creep.pos.isNearTo(source)) {
                creep.pickup(source)
            } else {
                goTo(creep, source.pos)
            }
        } else {
            if (source.store['energy'] <= 0) {
                delete creep.memory.sourceId
                return
            }
            if (creep.pos.isNearTo(source)) {
                creep.withdraw(source, 'energy')
            } else {
                goTo(creep, source.pos)
            }
        }
    } else {
        if (!creep.memory.targetId) {
            // 先看是否有建筑工地需要修理
            const constructionSites = room.find(FIND_CONSTRUCTION_SITES)
            if (constructionSites.length > 0) {
                let constructionSite: ConstructionSite | undefined | null
                const buildFlag = Game.flags[`${room.name}/build`]
                if (buildFlag) {
                    constructionSite = constructionSites.find((site) => site.pos.isEqualTo(buildFlag.pos))
                    if (!constructionSite) {
                        buildFlag?.remove()
                        return
                    }
                } else {
                    constructionSite = creep.pos.findClosestByPath(constructionSites)
                }
                if (constructionSite) {
                    creep.memory.targetId = constructionSite.id
                }
            } else if (room.controller && room.controller.level < 8 && !Game.flags[`${room.name}/helpBuilder/repair`]) {
                creep.memory.targetId = room.controller.id
            } else {
                // 修墙
                const walls = room.find(FIND_STRUCTURES, { filter: (s) => s.structureType === STRUCTURE_RAMPART })
                if (walls.length > 0) {
                    // 找血量最小的
                    const minWall = _.min(walls, (w) => w.hits)
                    if (minWall) {
                        creep.memory.targetId = minWall.id
                    }
                }
            }
        }
        if (!creep.memory.targetId) return
        const target = Game.getObjectById(creep.memory.targetId) as
            | ConstructionSite
            | StructureController
            | StructureRampart
        if (!target) {
            delete creep.memory.targetId
            return
        }

        let result: number
        if (target instanceof ConstructionSite) {
            result = creep.build(target)
        } else if (target instanceof StructureController) {
            result = creep.upgradeController(target)
        } else {
            result = creep.repair(target)
        }
        if (result === ERR_NOT_IN_RANGE) {
            creep.moveTo(target)
        }
    }
}
